#pragma once
#ifdef _DEBUG
#pragma comment(lib, "../thirdparty/spdlog/lib/spdlogd.lib")
#else
#pragma comment(lib, "../thirdparty/spdlog/lib/spdlog.lib")
#endif

#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_TRACE

#include <spdlog\spdlog.h>
#include <spdlog\common.h>
#include <spdlog\sinks\daily_file_sink.h>
#include <spdlog\async.h>

#include "../utils/util.h"

class Logger
{

public:
	static Logger& GetInstance() {
		static Logger m_instance;
		return m_instance;
	}

	void setDirPath(std::string dirpath_) {
		dirPath = dirpath_+ "/food_detect_.txt";
		typedef spdlog::sinks::daily_file_sink<std::mutex, spdlog::sinks::daily_filename_calculator> dateonly_daily_file_sink_mt;
		nml_logger = spdlog::create_async<dateonly_daily_file_sink_mt>("m_logger", dirPath.c_str(), 0, 0);
#ifdef _DEBUG
		nml_logger->set_level(spdlog::level::trace);
#else
		nml_logger->set_level(spdlog::level::trace);
#endif
		nml_logger->flush_on(spdlog::level::err);

		spdlog::flush_every(std::chrono::seconds(3));
	}

	auto GetLogger() { return nml_logger; }

private:
	Logger() {
		typedef spdlog::sinks::daily_file_sink<std::mutex, spdlog::sinks::daily_filename_calculator> dateonly_daily_file_sink_mt;
		nml_logger = spdlog::create_async<dateonly_daily_file_sink_mt>("m_logger", "logs/food_detect_.txt", 0, 0);

		nml_logger->set_pattern("%Y-%m-%d %H:%M:%S.%f <thread %t> [%l] [%@] %v"); // with timestamp, thread_id, filename and line number
		
		//spdlog::register_logger(nml_logger);

#ifdef _DEBUG
		nml_logger->set_level(spdlog::level::trace);
#else
		nml_logger->set_level(spdlog::level::trace);
#endif
		nml_logger->flush_on(spdlog::level::err);

		spdlog::flush_every(std::chrono::seconds(3));
	}

	~Logger() {
		spdlog::drop_all();
	}

	Logger(const Logger&) = delete;
	Logger& operator=(const Logger&) = delete;

private:
	std::shared_ptr<spdlog::logger> nml_logger;
	std::string dirPath;
};

#define LTrace(...) SPDLOG_LOGGER_CALL(Logger::GetInstance().GetLogger().get(), spdlog::level::trace, __VA_ARGS__)
#define LDebug(...) SPDLOG_LOGGER_CALL(Logger::GetInstance().GetLogger().get(), spdlog::level::debug, __VA_ARGS__)
#define LInfo(...) SPDLOG_LOGGER_CALL(Logger::GetInstance().GetLogger().get(), spdlog::level::info, __VA_ARGS__)
#define LWarn(...) SPDLOG_LOGGER_CALL(Logger::GetInstance().GetLogger().get(), spdlog::level::warn, __VA_ARGS__)
#define LError(...) SPDLOG_LOGGER_CALL(Logger::GetInstance().GetLogger().get(), spdlog::level::err, __VA_ARGS__)